﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;

namespace ConsoleProject
{
    /*
    AutoResetEvent		ManualResetEvent
http://blog.csdn.net/luminji/article/details/5472601

async await 异步实例
http://www.jb51.net/article/44575.htm
     * */
    class AsyncClass
    {
        //定义委托
        public delegate int MyDelegate(int num1, int num2);

        //计算 模拟耗时2秒 
        public int Sum(int num1, int num2)
        {
            ret_Result = num1 + num2;
            Console.Write("计算方法--------------\n");

            Thread.Sleep(2000); //模拟改方法耗时2s
            return num1 + num2;
        }
        /*
        static void Main(string[] args)
        {
            Console.Write("主方法： 开始 \n");
            AsyncClass cl = new AsyncClass();

            //cl.AsyncTest1(10,15);   //方法一
            //cl.AsyncTest2(6, 8);    //方法二
            //cl.AsyncTest3(5, 8); //方法三
            cl.AsyncTest4(5000);  //方法四


            Console.Write("主方法： 结束 \n");
            Console.ReadKey();
        }
  */






        #region  方法一： 调用回调函数

        public void AsyncTest1(int n1, int n2)
        {
            Thread.Sleep(2000); //模拟改方法耗时2s
            MyDelegate myDelegate = Sum;
            IAsyncResult asyncResult = myDelegate.BeginInvoke(n1, n2, callBack1, myDelegate);
        }
        public void callBack1(IAsyncResult async1)
        {
            if (async1 == null) return;
            //MyDelegate myDelgage = (MyDelegate)async1.AsyncState;  //AsyncState获取BeginInvoke 方法的第四个参数
            //int result = myDelgage.EndInvoke(async1);
            //Console.Write("回调函数 计算结果："+result);

            AsyncResult asyncResult = (AsyncResult)async1;
            MyDelegate myDelgage = (MyDelegate)asyncResult.AsyncDelegate;  //AsyncDelegate获取委托对象
            int result = myDelgage.EndInvoke(asyncResult);

            Console.Write("计算结果" + result);
        }
        #endregion





        #region   方法二：回调函数传参 可以是任何对象
        int ret_Result = 0;
        public void AsyncTest2(int n1, int n2)
        {
            MyDelegate myDelegate = Sum;

            //定义传给回调方法的参数
            Person person = new Person();
            person.name = "johnny";
            person.address = "中国上海";
            person.age = 18;
            IAsyncResult asyncResult = myDelegate.BeginInvoke(n1, n2, callBack2, person);

            Console.Write("继续做其他事");
            for (int i = 0; i < 10; i++)
            {
                Console.Write(" *\n\r");
            }
        }
        public void callBack2(IAsyncResult async1)
        {
            if (async1 == null) return;
            AsyncResult asyncResult = (AsyncResult)async1;
            MyDelegate myDelegate = (MyDelegate)asyncResult.AsyncDelegate;
            int result = myDelegate.EndInvoke(async1);  //获取返回值

            Person p = (Person)async1.AsyncState;  //AsyncState获取BeginInvoke 方法的第四个参数
            Console.Write("回调函数 计算结果：" + result + " ；\r\n       BeginInvoke 第四个参数传递对象：name:" + p.name + ",Age:" + p.age + ",Address:" + p.address);


        }
        #endregion



        #region   方法三：不带回调函数
        public void AsyncTest3(int n1, int n2)
        {
            MyDelegate myDelegate = Sum;


            IAsyncResult asyncResult = myDelegate.BeginInvoke(n1, n2, null, null);

            //WaitHandle waitHandle = asyncResult.AsyncWaitHandle;
            //waitHandle.WaitOne();

            //判断回调函数是否完成
            while (!asyncResult.IsCompleted)
            {
                Thread.Sleep(200);
                Console.Write("*");
            }

            int re = myDelegate.EndInvoke(asyncResult);
            Console.WriteLine("\n计算结果：" + re);
        }

        #endregion




        #region     方法四：WaitOne 辅助方法

        public void AsyncTest4(int sleepTime)
        {
            int threadID;
            MyDeleg mydeleg = new MyDeleg(TestMethod);
            IAsyncResult asynRes = mydeleg.BeginInvoke(sleepTime, out threadID, null, null);
            Thread.Sleep(2000);
            int cThreadID = AppDomain.GetCurrentThreadId();
            Console.WriteLine("主线程ID:"+cThreadID.ToString());
            asynRes.AsyncWaitHandle.WaitOne();  //执行该方法时主线程将等待辅助线程执行完毕，使两线程同步后再执行以下语句
            Console.WriteLine("执行其他方法");
            string ret = mydeleg.EndInvoke(out threadID, asynRes);//使用EndInvoke 获取返回结果和传入的ref / out 变量
            Console.WriteLine("线程ID:{0}:返回值：{1}",threadID,ret);

        }

        public delegate string MyDeleg(int sleepTime,out int threadID);
        public string TestMethod(int sleepTime, out int threadID)
        {
            Console.WriteLine("方法开始：");
            Thread.Sleep(sleepTime);
            threadID = AppDomain.GetCurrentThreadId();
            return "休眠" + sleepTime + "毫秒";
        }



        #endregion
    }

    public class Person
    {
        public string name { get; set; }
        public int age { get; set; }
        public string address { get; set; }
    }
}
